<template>
    <div class="device-manage">
        <div class="query-form">
            <el-form ref="form" :inline="true" :model="queryForm">
                <el-form-item label="设备名称" prop="deviceName">
                    <el-input v-model="queryForm.deviceName" placeholder="请输入设备名称" />
                </el-form-item>
                <el-form-item>
                    <el-button type="primary" @click="handleQuery">查询</el-button>
                    <el-button @click="handleReset('form')">重置</el-button>
                </el-form-item>
            </el-form>
        </div>
        <div class="base-table">
            <div class="action">
                <el-button type="primary" @click="handleCreate">新增</el-button>
                <el-button type="danger" @click="handlePatchDelete">批量删除</el-button>
            </div>
            <el-table :data="deviceList" @selection-change="handleSelectionChange" border cell-style="padding: 4px 0"
                max-height="600">
                <el-table-column type="selection" width="40" align="center" />
                <el-table-column v-for="item in columns" :key="item.prop" :prop="item.prop" :label="item.label"
                    :width="item.width" :formatter="item.formatter" align="center" />
                <el-table-column label="操作" width="280" align="center">
                    <template #default="scope">
                        <el-button size="mini" type="primary" @click="handleEdit(scope.row)">编辑</el-button>
                        <el-button size="mini" type="success" @click="handleControl(scope.row)">控制</el-button>
                        <el-button size="mini" type="info" @click="handleUpdateFirmware(scope.row)">升级</el-button>
                        <el-button size="mini" type="danger" @click="handleDelete(scope.row)">删除</el-button>
                    </template>
                </el-table-column>
            </el-table>
            <el-pagination class="pagination" background layout="prev, pager, next" :total="pager.totalCount"
                :page-size="pager.pageSize" @current-change="handleCurrentChange" />
        </div>
        <el-dialog :title="action == 'add' ? '设备新增' : '设备修改'" v-model="showModal" :close-on-click-modal="false"
            :show-close="false" width="550px" center>
            <el-form ref="dialogForm" :model="deviceForm" label-width="100px" :rules="rules">
                <el-form-item label="设备名称" prop="deviceName">
                    <el-input v-model="deviceForm.deviceName" placeholder="请输入设备名称" />
                </el-form-item>
                <el-form-item label="产品ID" prop="modelId" v-show="action == 'edit'">
                    <el-input v-model="deviceForm.modelId" :disabled="true" />
                </el-form-item>
                <el-form-item label="设备ID" prop="deviceId" v-show="action == 'edit'">
                    <el-input v-model="deviceForm.deviceId" :disabled="true" />
                </el-form-item>
                <el-form-item label="设备密钥" prop="deviceSecret" v-show="action == 'edit'">
                    <el-input v-model="deviceForm.deviceSecret" :disabled="true" />
                </el-form-item>
                <el-form-item label="物模型" prop="modelId">
                    <el-select v-model="deviceForm.modelId" size="medium" style="width: 100%;" clearable>
                        <el-option v-for="item in modelList" :key="item.modelId" :label="item.modelName"
                            :value="item.modelId">
                        </el-option>
                    </el-select>
                </el-form-item>
                <el-form-item label="所属组织" prop="groupId">
                    <el-cascader v-model="deviceForm.groupId" :options="groupList" :props="{
                        checkStrictly: true,
                        emitPath: false,
                        value: 'groupId',
                        label: 'groupName',
                    }" clearable style="width:100%" />
                </el-form-item>
                <el-form-item label="设备类型" prop="type">
                    <el-select v-model="deviceForm.type" size="medium" style="width: 100%;" clearable>
                        <el-option label="智能开关" value="1"></el-option>
                        <el-option label="智能插排" value="2"></el-option>
                        <el-option label="智能鱼缸灯" value="3"></el-option>
                        <el-option label="智能鱼缸插排" value="4"></el-option>
                        <el-option label="智能鱼缸喂食器" value="5"></el-option>
                        <el-option label="其它设备" value="0"></el-option>
                    </el-select>
                </el-form-item>
                <el-form-item label="是否公开" prop="isPublic">
                    <el-select v-model="deviceForm.isPublic" size="medium" style="width: 100%;" clearable>
                        <el-option label="是" value="1"></el-option>
                        <el-option label="否" value="0"></el-option>
                    </el-select>
                </el-form-item>
                <el-form-item label="设备图标" prop="icon">
                    <el-input v-model="deviceForm.icon" placeholder="请输入设备图标" />
                </el-form-item>
                <el-form-item label="视频地址" prop="videoUrl">
                    <el-input v-model="deviceForm.videoUrl" placeholder="请输入视频地址" />
                </el-form-item>
                <el-form-item label="固件版本" prop="version">
                    <el-input v-model="deviceForm.version" placeholder="请输入固件版本" />
                </el-form-item>
                <el-form-item label="固件地址" prop="firmwareUrl">
                    <el-input v-model="firmwareUrl" placeholder="请上传固件地址" :disabled="true" />
                </el-form-item>
                <el-form-item>
                    <el-upload class="upload-firmwareUrl" action="void" :http-request="uploadFile" :name="file"
                        :multiple="false" ref="upload" :show-file-list="false" :auto-upload="true">
                        <el-button size="small" type="primary">点击上传</el-button>
                    </el-upload>
                </el-form-item>
                <el-form-item label="备注" prop="remark">
                    <el-input v-model="deviceForm.remark" placeholder="请输入备注" />
                </el-form-item>
            </el-form>
            <template #footer>
                <span class="dialog-footer">
                    <el-button @click="handleClose">取消</el-button>
                    <el-button type="primary" @click="handleSubmit">确定</el-button>
                </span>
            </template>
        </el-dialog>
        <el-dialog :title="deviceForm.deviceName" v-model="showControl" :close-on-click-modal="false"
            :show-close="false" width="30%" center>
            <el-row>
                <el-col :span="24">
                    <div class="video">
                        <div id="video-container" v-if="showControl" />
                    </div>
                </el-col>
            </el-row>
            <el-row v-for="item in events" :key="item.id">
                <el-col :span="12" v-for="property in item.params" :key="property.id">
                    <div class="data-detail">
                        <text class="data-words">{{ property.name }}</text>
                        <text class="data-words-second">{{ property.value || property.value }}­ {{
                            property.unit }}</text>
                    </div>
                </el-col>
            </el-row>
            <el-row v-for="item in actions" :key="item.id">
                <el-col :span="12" v-for="property in item.input" :key="property.id">
                    <div class="data-detail">
                        <div class="data-words">
                            {{ property.name }}
                        </div>
                        <el-switch class="data-words-second" v-if="property.define.type == 'boolean'" active-value="1"
                            inactive-value="0" v-model="property.value" @click='performAction(property)' />
                        <el-input class="data-words-second" v-else-if="property.define.type == 'float'"
                            v-model="property.value" placeholder="" @keyup.enter="performAction(property)" />
                    </div>
                </el-col>
            </el-row>
            <template #footer>
                <span class="dialog-footer">
                    <el-button @click="handleControlClose">关闭</el-button>
                </span>
            </template>
        </el-dialog>
        <el-dialog v-model="showProgress" :close-on-click-modal="false" :show-close="false" width="450px" center>
            <el-progress :text-inside="true" :stroke-width="24" :percentage="upLoadProgress"
                status="success"></el-progress>
            <template #footer>
                <span class="dialog-footer">
                    <el-button @click="handleProgressClose">关闭</el-button>
                </span>
            </template>
        </el-dialog>
    </div>
</template>

<script>
import EZUIKit from "ezuikit-js";
import { getCurrentInstance, onMounted, reactive, ref, toRaw } from 'vue'
import axios from 'axios'
import utils from "../utils/utils";
export default {
    name: 'device',
    setup() {
        //获取Composition API上下文对象
        const { ctx, proxy } = getCurrentInstance();
        //初始化设备表单对象
        const queryForm = reactive({});
        //初始化设备列表数据
        const deviceList = ref([]);
        //初始化物模型列表数据
        const modelList = ref([]);
        //初始化分页对象
        const pager = reactive({
            pageNum: 1,
            pageSize: 10
        });
        //选中设备列表的对象
        const checkedDeviceIds = ref([]);
        //弹框显示对象
        const showModal = ref(false);
        //控制显示对象
        const showControl = ref(false);

        //控制进度显示对象
        const showProgress = ref(false);
        //上传进度
        const upLoadProgress = ref('');
        //固件地址
        const firmwareUrl = ref('');
        //新增设备表单对象
        const deviceForm = reactive({
            status: 1
        });
        //物模型属性列表
        const properties = ref([]);
        //物模型事件列表
        const events = ref([]);
        //物模型行为列表
        const actions = ref([]);
        //部门列表
        const groupList = ref([]);
        //定义设备操作行为
        const action = ref('add');
        //定义表单校验规则
        const rules = reactive({
            deviceName: [
                {
                    required: true,
                    message: "请输入设备名称",
                    trigger: "blur",
                }
            ],
            modelId: [
                {
                    required: true,
                    message: "请选择物模型",
                    trigger: "blur",
                }
            ],
            groupId: [
                {
                    required: true,
                    message: "请选择所属组织",
                    trigger: "blur",
                }
            ],
            type: [
                {
                    required: true,
                    message: "请选择设备类型",
                    trigger: "blur",
                },
            ],
            isPublic: [
                {
                    required: true,
                    message: "请选择是否公开",
                    trigger: "blur",
                },
            ]

        });
        //定义动态表格格式
        const columns = reactive([
            {
                label: "设备名称",
                prop: "deviceName"
            },
            {
                label: "设备类型",
                prop: "type",
                formatter(row, column, value) {
                    return {
                        1: '智能开关',
                        2: '智能插排',
                        3: '智能鱼缸灯',
                        4: '智能鱼缸插排',
                        5: '智能鱼缸喂食器',
                        0: '其它设备'
                    }[value]
                }
            },
            {
                label: "是否公开",
                prop: "isPublic",
                formatter(row, column, value) {
                    return {
                        1: '是',
                        0: '否'
                    }[value]
                }
            },
            {
                label: "备注",
                prop: "remark",
            },
            {
                label: "创建时间",
                prop: "createTime",
                formatter(row, column, value) {
                    return utils.formateDate(new Date(value));
                },
            }
        ]);
        //初始化设备表单对象
        const playerParams = reactive({
            autoplay: true,
            id: "video-container",
            accessToken: "",
            url: "",
            template: "simple", // simple - 极简版;standard-标准版;security - 安防版(预览回放);voice-语音版；
            width: 420,
            height: 280
        });

        var player = null;
        //初始化接口调用
        onMounted(() => {
            getDeviceList();
            getGroupList();
            getModelList();
        })
        // 获取设备列表
        const getDeviceList = async () => {
            let params = { ...queryForm, ...pager };
            try {
                const { list, total } = await proxy.$api.getDeviceList(params);
                deviceList.value = list;
                pager.totalCount = total;
            } catch (error) {
                console.log(proxy.$api);
            }
        };
        // 获取机构列表
        const getGroupList = async () => {
            try {
                const { list } = await proxy.$api.getGroupList({});
                groupList.value = list;
            } catch (e) {
                throw new Error(e);
            }
        }
        // 获取物模型列表
        const getModelList = async () => {
            try {
                const { list } = await proxy.$api.getAllModelList({});
                modelList.value = list;
            } catch (e) {
                throw new Error(e);
            }
        };
        //查询事件，获取设备列表
        const handleQuery = () => {
            getDeviceList();
        }
        // 重置查询表单
        const handleReset = (form) => {
            proxy.$refs[form].resetFields();
            getDeviceList();
        };
        // 分页事件处理
        const handleCurrentChange = (current) => {
            pager.pageNum = current;
            getDeviceList();
        };
        //设备单个删除
        const handleDelete = async (row) => {
            await proxy.$api.deviceDelete({
                deviceIds: [row.deviceId]
            })
            proxy.$message.success('删除成功');
            getDeviceList();
        }
        //批量删除
        const handlePatchDelete = async () => {
            if (checkedDeviceIds.value.length == 0) {
                proxy.$message.error('请选择要删除的设备');
                return;
            }
            const res = await proxy.$api.deviceDelete({
                deviceIds: checkedDeviceIds.value
            })
            if (res.rows > 0) {
                proxy.$message.success('删除成功');
                getDeviceList();
            } else {
                proxy.$message.error('删除失败');
            }

        }
        //设备固件更新
        const handleUpdateFirmware = async (row) => {
            await proxy.$api.updateDeviceFirmware({
                deviceId: row.deviceId
            })
            proxy.$message.success('更新成功');
            getDeviceList();
        }
        //表格多选
        const handleSelectionChange = (list) => {
            let arr = [];
            list.map(item => {
                arr.push(item.deviceId);
            })
            checkedDeviceIds.value = arr;
        }
        //设备新增
        const handleCreate = () => {
            action.value = 'add';
            showModal.value = true;
        }
        // 设备弹窗关闭
        const handleClose = () => {
            showModal.value = false;
            firmwareUrl.value = '';
            handleReset("dialogForm");
        };
        //设置控制弹窗关闭
        const handleControlClose = () => {
            showControl.value = false;
            properties.value = [];
            events.value = [];
            actions.value = [];
            player.stop();
            proxy.$websocket.ws.close();
        }
        // 设备提交
        const handleSubmit = () => {
            proxy.$refs.dialogForm.validate(async (valid) => {
                if (valid) {
                    deviceForm.firmwareUrl = firmwareUrl.value;
                    let params = toRaw(deviceForm);
                    params.action = action.value;
                    if (action.value == 'add') {
                        let res = await proxy.$api.deviceSubmit(params);
                        proxy.$message.success("设备创建成功");
                    } else {
                        let res = await proxy.$api.deviceUpdate(params);
                        proxy.$message.success("设备修改成功");

                    }
                    showModal.value = false;
                    firmwareUrl.value = '';
                    handleReset("dialogForm");
                    getDeviceList();
                }
            });
        };
        // 设备编辑
        const handleEdit = (row) => {
            action.value = "edit";
            showModal.value = true;
            proxy.$nextTick(async () => {
                try {
                    const { device } = await proxy.$api.getDeviceById({ deviceId: row.deviceId });
                    firmwareUrl.value = device.firmwareUrl;
                    Object.assign(deviceForm, device);
                } catch (error) {
                    console.log(proxy.$api);
                }
            });
        };
        //设备控制
        const handleControl = (row) => {
            showControl.value = true;
            proxy.$nextTick(async () => {
                try {
                    const { device } = await proxy.$api.getDeviceById({ deviceId: row.deviceId });
                    Object.assign(deviceForm, device);
                    const params = { deviceId: row.deviceId };
                    const modelParams = { modelId: device.modelId };
                    getModelInfo(params, modelParams);
                    initWebSocket(row);
                    getVideo(row);
                } catch (error) {
                    console.log(proxy.$api);
                }
            });
        };
        // 获取设备物模型属性
        const getModelInfo = async (params, modelParams) => {
            try {
                // const { list } = await proxy.$api.getModelPropertyByDeviceId(params);
                // properties.value = list;

                const { model } = await proxy.$api.getModelInfoByModelId(modelParams);
                properties.value = model.properties;
                events.value = model.events;
                actions.value = model.actions;

            } catch (error) {
                console.log(proxy.$api);
            }
        };

        // 获取视频授权码
        const getVideo = async (row) => {
            let params = { deviceId: row.deviceId };
            try {
                const { accessToken, url } = await proxy.$api.getAccessToken(params);
                playerParams.accessToken = accessToken;
                playerParams.url = url;
            } catch (error) {
                console.log(proxy.$api);
            }

            player = new EZUIKit.EZUIKitPlayer(playerParams)
        };

        const changeStatus = async (item) => {
            var jsonObject = {};
            jsonObject[item.id] = item.value;

            const token = proxy.$storage.getItem("token");
            const actions = {
                action: 2,
                token: token,
                deviceId: deviceForm.deviceId,
                message: jsonObject
            };
            // send向服务器发送消息
            proxy.$websocket.ws.send(JSON.stringify(actions));
        };

        const performAction = async (item) => {
            var jsonObject = {};
            jsonObject[item.id] = item.value;

            const token = proxy.$storage.getItem("token");
            const actions = {
                action: 2,
                token: token,
                deviceId: deviceForm.deviceId,
                message: jsonObject
            };
            // send向服务器发送消息
            proxy.$websocket.ws.send(JSON.stringify(actions));
        };

        const initWebSocket = (row) => {
            const token = proxy.$storage.getItem("token");
            // proxy.$websocket.ws = new WebSocket("wss://www.geniusk.com/ws");   // 填写通讯地址
            proxy.$websocket.ws = new WebSocket("ws://localhost:8090/ws");
            proxy.$websocket.setWs(proxy.$websocket.ws);
            proxy.$websocket.ws.onopen = () => {
                console.log("连接成功");
                const actions = {
                    action: 1,
                    token: token,
                    deviceId: row.deviceId
                };
                // send向服务器发送消息
                proxy.$websocket.ws.send(JSON.stringify(actions));
            };
            proxy.$websocket.ws.onerror = (e) => {
                console.log("连接错误信息", e);
            };
            proxy.$websocket.ws.onclose = () => {
                console.log("连接已断开");
            };
            proxy.$websocket.ws.onmessage = (msg) => {
                var obj = msg.data;
                var json = JSON.parse(obj);
                properties.value.forEach(item => {
                    if (json[item.id] !== undefined) {
                        if (json.hasOwnProperty(item.id)) {
                            // 更新值
                            item.value = json[item.id].toString();
                        }
                    }
                });
                events.value.forEach(item => {
                    item.params.forEach(prop => {
                        if (json[prop.id] !== undefined) {
                            if (json.hasOwnProperty(prop.id)) {
                                // 更新值
                                prop.value = json[prop.id].toString();
                            }
                        }
                    });
                });
                actions.value.forEach(item => {
                    item.input.forEach(prop => {
                        if (json[prop.id] !== undefined) {
                            if (json.hasOwnProperty(prop.id)) {
                                // 更新值
                                prop.value = json[prop.id].toString();
                            }
                        }
                    });
                });
            };
        };

        //上传文件直传
        const uploadFile = async (file) => {
            const { uploadUrl, fileUrl } = await proxy.$api.getUploadUrl({ fileName: file.file.name, fileSize: file.file.size, fileType: "4" });
            await axios.request({
                url: uploadUrl,
                method: 'PUT',
                data: file.file,
                headers: { 'Content-Type': 'application/octet-stream' },
                onUploadProgress: function (progressEvent) {
                    // 对原生进度事件的处理
                    if (progressEvent.lengthComputable) {
                        upLoadProgress.value = Math.round(progressEvent.loaded / progressEvent.total * 100) + ""//实时获取上传进度
                        if (upLoadProgress.value === '100') {
                            showProgress.value = false;
                            firmwareUrl.value = fileUrl;
                        } else {
                            showProgress.value = true;
                        }
                    }
                }
            })
        };
        // 上传进度
        const handleProgressClose = () => {
            showProgress.value = false;
        }

        return {
            queryForm,
            deviceList,
            modelList,
            columns,
            playerParams,
            player,
            pager,
            checkedDeviceIds,
            showModal,
            showControl,
            showProgress,
            upLoadProgress,
            firmwareUrl,
            deviceForm,
            properties,
            events,
            actions,
            groupList,
            action,
            rules,
            getDeviceList,
            getGroupList,
            getModelList,
            handleQuery,
            handleReset,
            handleCurrentChange,
            handleDelete,
            handlePatchDelete,
            handleUpdateFirmware,
            handleSelectionChange,
            handleCreate,
            handleClose,
            handleSubmit,
            handleControlClose,
            handleEdit,
            handleControl,
            getModelInfo,
            getVideo,
            changeStatus,
            performAction,
            initWebSocket,
            uploadFile,
            handleProgressClose
        }
    }
}
</script>

<style lang="scss">
.video {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;

    .video-container {
        align-self: center;
    }
}

.data-detail {
    align-self: center;
    display: flex;
    flex-direction: column;
    justify-content: center;

    .data-words {
        margin-top: 30px;
        margin-bottom: 10px;
        font-size: 15px;
        font-weight: 800;
        align-self: center;
    }

    .data-words-second {
        font-size: 15px;
        font-weight: 300;
        color: gray;
        align-self: center;
    }
}
</style>